package com.bjy.qa.util.json;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.Predicate;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedHashMap;
import java.util.List;

public class JsonHelper {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private JsonObject json;
    private String jsonStr;

    /**
     * 构造函数
     *
     * @param object 可以传入 json String 或 JsonObject
     */
    public JsonHelper(Object object) {
        if (object instanceof JsonObject) {
            json = (JsonObject) object;
            jsonStr = ((JsonObject) object).toString();
        } else if (isJson(object)) {
            jsonStr = JsonHelper.toJsonString(new JsonParser().parse(object.toString()).getAsJsonObject());
        } else {
            throw new IllegalArgumentException("创建 JsonHelper 错误，参数异常，object 必须为 JsonObject 或 json 字符串。");
        }
    }

    /**
     * 判断是否是 json 格式的字符串
     *
     * @param object json 字符串
     * @return
     */
    public static boolean isJson(Object object) {
        if (!(object instanceof String)) return false;
        try {
            new JsonParser().parse(object.toString()).getAsJsonObject();
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 将指定对象序列化为 Json 字符串
     *
     * @param object 对象
     * @return
     */
    public static String toJsonString(Object object) {
        Gson gson = new Gson();
        try {
            return gson.toJson(object);
        } catch (JsonSyntaxException e) {
            return "";
        }
    }

    /**
     * 得到 jsong 对象
     *
     * @return
     */
    public JsonObject getJsonObject() {
        if (json == null) {
            json = new JsonParser().parse(jsonStr).getAsJsonObject();
        }
        return json;
    }

    /**
     * 得到一个实体 bean 对象
     * 此方法将指定的Json反序列化为指定类的对象。事实并非如此
     *
     * @param classOfT T的类
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @param <T>
     * @return
     */
    public <T> T getBean(Class<T> classOfT, String jsonPath, Predicate... filters) {
        Object object = get(jsonPath, filters);
        Gson gson = new Gson();
        try {
            return gson.fromJson(gson.toJson(object), classOfT);
        } catch (JsonSyntaxException e) {
            return null;
        }
    }

    /**
     * 得到一个 string 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public String getString(String jsonPath, Predicate... filters) {
        return get(String.class, jsonPath, filters);
    }

    /**
     * 得到一个 int 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public Integer getInteger(String jsonPath, Predicate... filters) {
        return get(Integer.class, jsonPath, filters);
    }

    /**
     * 得到一个 Boolean 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public Boolean getBoolean(String jsonPath, Predicate... filters) {
        return get(Boolean.class, jsonPath, filters);
    }

    /**
     * 得到一个 Long 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public Long getLong(String jsonPath, Predicate... filters) {
        return get(Long.class, jsonPath, filters);
    }

    /**
     * 得到一个 double 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public double getDouble(String jsonPath, Predicate... filters) {
        return get(Double.class, jsonPath, filters);
    }

    /**
     * 得到一个 List 类型对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @return
     */
    public List getList(String jsonPath, Predicate... filters) {
        return get(List.class, jsonPath, filters);
    }

    public LinkedHashMap getObjetct(String jsonPath, Predicate... filters) {
        return get(LinkedHashMap.class, jsonPath, filters);
    }

    /**
     * 按指定类型得到对象
     *
     * @param clazz    指定类型
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @param <T>
     * @return
     */
    private <T> T get(Class clazz, String jsonPath, Predicate... filters) {
        Object object = get(jsonPath, filters);

        if (null == object || clazz.isInstance(object)) {
            return (T) object;
        } else {
            throw new ClassCastException("类型转换失败。" + object.getClass().getName() + " 转 " + clazz.getName() + " 失败。");
        }
    }

    /**
     * 得到匹配的对象
     *
     * @param jsonPath json 的 xpath 字符串
     * @param filters  应用在 xpath 中的过滤器
     * @param <T>
     * @return
     */
    public <T> T get(String jsonPath, Predicate... filters) {
        if (jsonStr == null || jsonPath.isEmpty()) {
            throw new IllegalArgumentException("参数错误，jsonPath不能为空");
        }
        logger.debug("匹配对象:" + jsonStr + ", 表达式: " + jsonPath);

        try {
            Object obj = JsonPath.read(jsonStr, jsonPath, filters);
            return (T) obj;
        } catch (PathNotFoundException e) {
            return null;
        }
    }

    @Override
    public String toString() {
        return this.getJsonObject().toString();
    }
}
